/*
 * @filename CustomHttpBasicServerAuthenticationEntryPoint.java
 * @author barry
 * @version 0.0.1
 * @date 2020年1月14日
 */
package com.bnzj.core.webflux.security;

import com.bnzj.core.rest.ResponseResult;
import com.bnzj.core.rest.ResultCode;
import com.bnzj.core.util.JsonUtils;
import com.bnzj.core.util.LogUtils;
import com.bnzj.core.web.constant.CommonWebEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.Charsets;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.server.ServerAuthenticationEntryPoint;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.util.Arrays;

/**
 * @author barry
 * @date 2020-01-14
 */
@Slf4j
public class CustomServerAuthenticationEntryPoint implements ServerAuthenticationEntryPoint {
    @Override
    public Mono<Void> commence(ServerWebExchange exchange, AuthenticationException e) {
        //return Mono.fromRunnable(() -> {
        ResponseResult<?> responseResult ;
        if(e.getCause() != null && e.getCause().toString().indexOf("JwtValidationException") > 0){
            responseResult = new ResponseResult<>(new ResultCode(CommonWebEnum.TOKEN_INVALID.getCode(), "令牌过期！"));
        }else if(e.getCause() != null && e.getCause().toString().indexOf("JwtException")>0){
            responseResult = new ResponseResult<>(new ResultCode(CommonWebEnum.TOKEN_INVALID.getCode(), "无效令牌！"));
        }else if(e instanceof InsufficientAuthenticationException){
            responseResult = new ResponseResult<>(new ResultCode(CommonWebEnum.TOKEN_INVALID.getCode(), CommonWebEnum.TOKEN_INVALID.getMsg()));
        }else{
            responseResult = new ResponseResult<>(new ResultCode(CommonWebEnum.ACCESS_DENIED.getCode(), CommonWebEnum.ACCESS_DENIED.getMsg()));
        }
        LogUtils.warn(log, exchange.getRequest().getURI().toString() + "令牌校验失败！", e, 20);
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        setResponseCorsHeaders(exchange);
        DataBuffer buffer = response.bufferFactory().wrap(JsonUtils.objToJson(responseResult).getBytes(Charsets.UTF_8));
        return response.writeWith(Mono.just(buffer));
        //response.getHeaders().set(WWW_AUTHENTICATE, this.headerValue);
        // });
    }

    //@Autowired
    //private CorsWebFilter corsFilter;
    private void setResponseCorsHeaders(ServerWebExchange exchange){
        ServerHttpResponse response = exchange.getResponse();
        HttpHeaders responseHeaders = response.getHeaders();
        responseHeaders.addAll(HttpHeaders.VARY, Arrays.asList(HttpHeaders.ORIGIN,
                HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS));
        responseHeaders.setAccessControlAllowOrigin("*");
        responseHeaders.setAccessControlAllowMethods(Arrays.asList(exchange.getRequest().getMethod()));
        responseHeaders.setAccessControlAllowHeaders(exchange.getRequest().getHeaders().getAccessControlRequestHeaders());
    }
}
